package com.pinapel.aixml.models.xml;

import java.util.ArrayList;
import java.util.Iterator;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.pinapel.aixml.Logger;


/** 
 * @author karloz
 * @since 11/2/2012 
 */

public class DomModel {
	
	/*
	 * Members
	 */
	private Node mTree;	
	
	/**
	 * @param tree DOM root node
	 */
	public DomModel(Node tree){
		this.mTree = tree;
		
	}
	
	/**
	 * @param  id Integer sequence that denotes the node's position inside DOMTree
	 * @return Node (DomTree node)
	 */
	public DomNode getNode(NodeID id){
		int head = 0;
		int index = 0;
		Node root = mTree;
		
		for (Iterator<Integer> it = id.getList().iterator();it.hasNext();){
			Node child = root.getFirstChild();
			head = it.next();
			while(child!=null && index < head){
				child = child.getNextSibling();
				index++;
			}
			index = 0;
			root = child;
		}
		
		if (root==null){
			Logger.log(" (DomNode.getNode) nodo obtenido nulo.");
		}		
		return new DomNode(root);		
	}
	
	/**
	 * @param id Integer sequence that denotes the node's position inside DOMTree
	 * @return short node type
	 * <p><ul>ATTRIBUTE_NODE</ul>        
		  <ul>CDATA_SECTION_NODE</ul>   
          <ul>COMMENT_NODE</ul>   
          <ul>DOCUMENT_FRAGMENT_NODE</ul>   
          <ul>DOCUMENT_NODE</ul>   
          <ul>DOCUMENT_TYPE_NODE</ul>   
          <ul>ELEMENT_NODE</ul>   
          <ul>ENTITY_NODE</ul>   
          <ul>ENTITY_REFERENCE_NODE</ul>   
          <ul>NOTATION_NODE</ul>   
          <ul>PROCESSING_INSTRUCTION_NODE</ul>   
          <ul>TEXT_NODE</ul>   
         </p>
	 */
	public short getType(NodeID id){
		return mTree.getNodeType();
		
	}
	
	/**	 
	 * @param id Integer sequence that denotes the node's position inside DOMTree
	 */
	public void deleteNode(NodeID id){
		int last = id.getLast();
		id.getList().remove(id.getList().size()-1);
		DomNode father = this.getNode(id); 
		
		ArrayList<Integer> newNodeId = new ArrayList<Integer>();
		newNodeId.add(last);
		
		DomNode child = father.getNode(new NodeID(newNodeId));		
		
		if (father.getDomNode().removeChild(child.getDomNode())==null){
			System.out.println("Error al borrar");
		}
	}
	
	/**	  
	 * @param id Integer sequence that denotes the node's position inside DOMTree.
	 * @return DomNode A copy of the node specified by id.
	 */
	public DomNode copyNode(NodeID id){
		return this.getNode(id).clone();
	}
	
	
	public DomNode copyNodeDeep(NodeID id){
		return this.getNode(id).cloneDeep();
	}
	
	/**
	 * 
	 * @param node Node that need to be inserted
	 * @param position Integer sequence that denotes the node's position inside DOMTree.
	 */
	public void insertNode(DomNode node,NodeID position){
		int last = (position.getLast()!=0)? position.getLast() : 0;
		position.getList().remove(position.getList().size()-1);
		DomNode dNode = this.getNode(position);
		NodeList children = dNode.getDomNode().getChildNodes();
		if (last==children.getLength()){
			last--;
		}
		if (children.item(last)==null){
			dNode.getDomNode().appendChild(node.getDomNode());
		}else{
			dNode.getDomNode().insertBefore(node.getDomNode(), children.item(last));
		}
	}
	
	/**
	 * 
	 * @return DomNode text representation
	 */
	
	public String getTextVersion(){
		return (new DomNode(mTree)).getTextVersion();
	}
	
	/**	 
	 * @param id Node to be moved
	 * @param position Final position
	 */
	
	public void moveNode(NodeID id,NodeID position){
		DomNode tmpNode = this.getNode(id);
		this.insertNode(tmpNode, position);
	}
	
	/**	 
	 * @return Node instance associated with this DomModel instance. 
	 */
	public Node getDomNode(){
		return this.mTree;
	}
	
	/**
	 * @return new DomModel cloned instance 
	 */
	public DomModel clone(){
		return new DomModel(this.mTree.cloneNode(false));
	}

	/**
	 * @return new DomModel deep cloned instance (his childs are cloned too) 
	 */
	public DomModel cloneDeep(){
		return new DomModel(this.mTree.cloneNode(true));
	}
	
	/** 
     * @param id Position inside DOMTree
     * @return String array that contains a string representation of id childs.
     */
    public String[] childsToString(NodeID id){
            String[] data;
            NodeList nodeList;
            if (id.getList().size()==0){
                    nodeList = ((Document)this.mTree).getChildNodes();                      
            }else{          
                    nodeList = this.getNode(id).getDomNode().getChildNodes();
            }
                    
            data = new String[nodeList.getLength()];
            for (int i=0;i<nodeList.getLength();i++){
                    if (((Node)nodeList.item(i)).getNodeType()!=Node.TEXT_NODE){
                            data[i] = ((Element)nodeList.item(i)).getTagName();                             
                    }
            }                       
            
            return data;
    }
	
}
